package com.wechat.page.contact.select;

import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;

import com.swak.entity.Toggle;
import com.swak.fx.support.Dialogs;
import com.swak.fx.support.FXMLView;
import com.swak.fx.support.Toast.ToastConfig;
import com.swak.fx.support.Window;
import com.swak.fx.support.ui.UI.Themes;
import com.swak.ui.EventListener;
import com.wechat.Cons;
import com.wechat.dto.ChatAddContactsDTO;
import com.wechat.dto.ChatDTO;
import com.wechat.dto.ContactDTO;
import com.wechat.dto.ContactFindDTO;
import com.wechat.page.MainPage;
import com.wechat.page.api.ChatApi;
import com.wechat.page.api.ContactApi;
import com.wechat.page.comps.TitleFixComp;

import javafx.beans.property.ListProperty;
import javafx.beans.property.ObjectProperty;
import javafx.beans.property.SimpleListProperty;
import javafx.beans.property.SimpleObjectProperty;
import javafx.collections.FXCollections;
import javafx.geometry.Insets;
import javafx.scene.control.ButtonType;
import javafx.scene.layout.GridPane;
import javafx.scene.layout.Priority;
import javafx.stage.Stage;

/**
 * 联系人选择
 * 
 * @author lifeng
 */
@FXMLView(title = "群聊管理", value = "ContactSelect.fxml", css = "ContactSelect.css", stageStyle = "TRANSPARENT", singleton = false)
public class ContactSelect extends Window implements EventListener {

	private TitleFixComp titleComp;
	private ContactSelectSide contactSelectSide;
	private ContactSelectMain contactSelectMain;

	@Autowired
	private ContactApi contactApi;
	@Autowired
	private ChatApi chatApi;

	public ContactSelect(Stage stage) {
		super(stage, MainPage.ADJUST_SIZE);
		this.setResizeAble(false);
		this.titleComp = this.NewComp(TitleFixComp.class);
		this.titleComp.titleProperty().set("群聊管理");
		this.contactSelectSide = this.NewPage(ContactSelectSide.class);
		this.contactSelectMain = this.NewPage(ContactSelectMain.class);
	}

	@Override
	public void initializeParts() {
		super.initializeParts();
		this.addChild(this.titleComp.getRoot());
		GridPane.setConstraints(this.titleComp.getRoot(), 0, 0);
		GridPane.setColumnSpan(this.titleComp.getRoot(), 2);
		GridPane.setHgrow(this.titleComp.getRoot(), Priority.ALWAYS);
		GridPane.setVgrow(this.titleComp.getRoot(), Priority.NEVER);

		this.addChild(this.contactSelectSide.getRoot());
		GridPane.setConstraints(this.contactSelectSide.getRoot(), 0, 1);
		GridPane.setHgrow(this.contactSelectSide.getRoot(), Priority.NEVER);
		GridPane.setVgrow(this.contactSelectSide.getRoot(), Priority.ALWAYS);

		this.addChild(this.contactSelectMain.getRoot());
		GridPane.setConstraints(this.contactSelectMain.getRoot(), 1, 1);
		GridPane.setHgrow(this.contactSelectMain.getRoot(), Priority.ALWAYS);
		GridPane.setVgrow(this.contactSelectMain.getRoot(), Priority.ALWAYS);

		GridPane.setMargin(this.titleComp.getRoot(),
				new Insets(MainPage.ADJUST_SIZE, MainPage.ADJUST_SIZE, 0, MainPage.ADJUST_SIZE));
		GridPane.setMargin(this.contactSelectSide.getRoot(),
				new Insets(0, 0, MainPage.ADJUST_SIZE, MainPage.ADJUST_SIZE));
		GridPane.setMargin(this.contactSelectMain.getRoot(),
				new Insets(0, MainPage.ADJUST_SIZE, MainPage.ADJUST_SIZE, 0));
	}

	@Override
	public void setupEventHandlers() {
		super.setupEventHandlers();
		this.contactSelectSide.$on(ContactSelectSide.ToggleEvent, this::onContactToggle);
		this.contactSelectMain.$on(ContactSelectMain.ToggleEvent, this::onContactToggle);
		this.contactSelectMain.$on(ContactSelectMain.ConfrimEvent, this::onConfirm);
	}

	private void onConfirm(Object o) {
		List<ContactDTO> contacts = this.contactsProperty.stream().filter(t -> t.isActive()).map(t -> t.getValue())
				.toList();
		if (com.swak.utils.Lists.isEmpty(contacts)) {
			this.$toast(ToastConfig.of().setMessage("设置联系人！").setTheme(Themes.Warning)).show();
			return;
		}

		this.doConfirm(contacts);
	}

	// 创建一个群聊天
	private void doConfirm(List<ContactDTO> contacts) {
		this.$runContextCompleteWithUI(() -> this.chatApi
				.create(new ChatAddContactsDTO().setChat(this.chatProperty.get()).setContacts(contacts)))
				.thenAccept(newChat -> this.$post(Cons.Event_Chat_Select, newChat))
				.thenAccept(res -> this.forceClose());
	}

	@SuppressWarnings("unchecked")
	private void onContactToggle(Object o) {
		Toggle<Object> toggle = (Toggle<Object>) o;
		int index = this.contactsProperty.indexOf(toggle);
		if (index >= 0) {
			Toggle<ContactDTO> me = this.contactsProperty.get(index);
			this.contactsProperty.set(index, me.setActive(toggle.isActive()));
		}
	}

	@Override
	public void setupBindings() {
		super.setupBindings();
		this.contactSelectSide.contactsProperty().bind(contactsProperty);
		this.contactSelectMain.contactsProperty().bind(contactsProperty);
	}

	@Override
	protected boolean beforeClose() {
		ButtonType ok = Dialogs.confirm(this.getStage(), "提醒", "确认取消修改？");
		if (ok == ButtonType.CANCEL) {
			return false;
		}
		return true;
	}

	// ================================================================================
	// 异步加载数据
	// ================================================================================
	@Override
	public void mounted() {
		super.mounted();

		this.$run(() -> this.load());
	}

	private void load() {
		if (LOGGER.isDebugEnabled()) {
			LOGGER.debug("[联系人列表] - 准备加载数据");
		}
		ContactFindDTO find = new ContactFindDTO();
		this.contactApi.friends(find).thenAccept(contacts -> {
			if (LOGGER.isDebugEnabled()) {
				LOGGER.debug("[联系人列表] - 加载数据:{}", contacts.size());
			}
			this.$runUI(() -> this.contactsProperty().addAll(
					contacts.stream().map(ct -> new Toggle<ContactDTO>().setActive(false).setValue(ct)).toList()));
		});
	}

	// ================================================================================
	// Properties
	// ================================================================================
	private final ListProperty<Toggle<ContactDTO>> contactsProperty = new SimpleListProperty<>(
			FXCollections.observableArrayList());

	public ListProperty<Toggle<ContactDTO>> contactsProperty() {
		return contactsProperty;
	}

	private final ObjectProperty<ChatDTO> chatProperty = new SimpleObjectProperty<>();

	public ContactSelect setChat(ChatDTO chat) {
		this.chatProperty.set(chat);
		return this;
	}

	/**
	 * 创建窗口
	 * 
	 * @return
	 */
	public static ContactSelect New() {
		return ContactSelect.New(ContactSelect.class, Window.createStage(true));
	}
}
